#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define TNUM 4
typedef void (*func_t)(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcond);
volatile bool quit = false;

class ThreadData
{
public:
    ThreadData(const std::string &name, func_t func, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
        :name_(name)
        ,func_(func)
        ,pmtx_(pmtx)
        ,pcond_(pcond)
    {}

public:
    std::string name_;
    func_t func_;
    pthread_mutex_t *pmtx_;
    pthread_cond_t *pcond_;
};

void func1(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);

        pthread_cond_wait(pcond, pmtx); // 默认该线程在执行的时候，wait代码被执行，当前线程会立即被阻塞
        cout << name << " running" << endl;

        pthread_mutex_unlock(pmtx);
    }
}

void func2(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);

        pthread_cond_wait(pcond, pmtx); // 默认该线程在执行的时候，wait代码被执行，当前线程会立即被阻塞
        cout << name << " running" << endl;
        
        pthread_mutex_unlock(pmtx);
    }
}
void func3(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);

        pthread_cond_wait(pcond, pmtx); // 默认该线程在执行的时候，wait代码被执行，当前线程会立即被阻塞
        cout << name << " running" << endl;

        pthread_mutex_unlock(pmtx);
    }
}
void func4(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);

        pthread_cond_wait(pcond, pmtx); // 默认该线程在执行的时候，wait代码被执行，当前线程会立即被阻塞
        cout << name << " running" << endl;

        pthread_mutex_unlock(pmtx);
    }
}
void *Entry(void* args)//相当于一层软件层
{
    ThreadData* td = (ThreadData*)args;// td在每一个线程自己私有的栈空间中保存
    td->func_(td->name_, td->pmtx_, td->pcond_);// 他也是一个函数
    delete td;
    return  nullptr;
}

int main()
{
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    pthread_mutex_init(&mtx, nullptr);
    pthread_cond_init(&cond, nullptr);

    pthread_t tids[TNUM];
    func_t funcs[TNUM] = {func1, func2, func3, func4};
    for (int i = 0; i < TNUM; i++)
    {
        std::string name = "Thread ";
        name += std::to_string(i+1);
        ThreadData *td = new ThreadData(name, funcs[i], &mtx, &cond);
        pthread_create(tids + i, nullptr, Entry, (void*)td);
    }

    sleep(5);

    int cnt = 10;
    while (cnt)
    {
        cout << "resume thread run code ... " << cnt-- << endl;
        pthread_cond_signal(&cond);// 一个一个唤醒
        pthread_cond_broadcast(&cond);// 全部唤醒
        sleep(1);
    }

    cout << "ctrl done" << endl;
    quit = true;
    pthread_cond_broadcast(&cond);
    
    for (int i = 0; i < TNUM; i++)
    {
        pthread_join(tids[i], nullptr);
        std::cout << "thread: " << tids[i] << " quit" << std::endl;
    }

    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);

    return 0;
}